home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / mopd / mopd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-11  |  10.5 KB  |  464 lines

  1. /*
  2.  * MOP server daemon.
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <sys/file.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <net/if_arp.h>
  10. #include <netinet/if_ether.h>
  11. #include <netEther.h>
  12. #ifndef mip
  13. #define mips 1
  14. #define notreallymips
  15. #endif
  16. #ifndef LANGUAGE_C
  17. #define LANGUAGE_C
  18. #endif
  19. #ifndef MIPSEL
  20. #define MIPSEL
  21. #endif
  22. #include <ds3100.md/sys/exec.h>
  23. #ifdef notreallymips
  24. #undef mips
  25. #endif
  26. #include <host.h>
  27. #include <mopd.h>
  28. #include <signal.h>
  29. #include <varargs.h>
  30. #include <time.h>
  31. #include <string.h>
  32.  
  33. Net_EtherAddress myAddr;
  34. Net_EtherAddress multiAddr;
  35.  
  36. unsigned char broadcast[] = MOP_BROADCAST;
  37.  
  38. int debug = 0;        /* Flag for debug mode. */
  39.  
  40. extern int errno;
  41.  
  42. #define TIMEOUTSEC 20
  43.  
  44. #define WAITING 0
  45. #define SENDING 1
  46. #define DONE    2
  47.  
  48. int mode=WAITING;    /* The state we're in. */
  49. int seq, seqHi;        /* The current sequence number. */
  50. int bootFd;        /* The boot program fd. */
  51. int mopFd;        /* The mop device fd. */
  52. u_char client[6];    /* The client we're dealing with. */
  53. int loadAddr, length, startAddr, fileOffset; /* Boot file parameters. */
  54. char filename[100];
  55.  
  56. static void log();
  57. int timer();
  58.  
  59. #if 0
  60. static char    *mopdlog = "/sprite/admin/mopdlog";
  61. static char    *openFlags = "a+";
  62. #else
  63. static char    *mopdlog = "/dev/syslog";
  64. static char    *openFlags = "w";
  65. #endif
  66.  
  67. void
  68. main(argc,argv)
  69.     int argc;
  70.     char **argv;
  71. {
  72.     unsigned char buf[BUF_LEN];
  73.     int len;
  74.     u_char us[6], them[6];
  75.     char myName[50];
  76.     mopHdr *mopHdrPtr = (mopHdr *)buf;
  77.     Host_Entry *myEntry, *theirEntry;
  78.     Net_Address theirNetAddress;
  79.     int        i;
  80.  
  81.     multiAddr = * (Net_EtherAddress *) broadcast;
  82.     if (gethostname(myName,50)<0) {
  83.     perror("gethostname");
  84.     exit(-1);
  85.     }
  86.     myEntry = Host_ByName(myName);
  87.     if (myEntry == NULL) {
  88.     perror("Host_ByName");
  89.     exit(-1);
  90.     }
  91.     for (i = 0; i < myEntry->numNets; i++) {
  92.     if (myEntry->nets[i].netAddr.type == NET_ADDRESS_ETHER) {
  93.         (void) Net_GetAddress(&myEntry->nets[i].netAddr,
  94.             (Address) &myAddr);
  95.         break;
  96.     }
  97.     }
  98.     Host_End();
  99.     for (argc--, argv++ ; argc > 0 ; argc--, argv++) {
  100.     if (argv[0][0] == '-') {
  101.         switch (argv[0][1]) {
  102.         case 'd':
  103.             debug++;
  104.             break;
  105.         }
  106.         }
  107.     }
  108.  
  109.     if (debug==0) {
  110.     if (fork()) exit(0);
  111.     }
  112.  
  113.     signal(SIGALRM, timer);
  114.  
  115.     mopFd = open(MOP_DEVICE, O_RDWR, 0);
  116.     if (mopFd < 0) {
  117.     perror(MOP_DEVICE);
  118.     exit(-1);
  119.     }
  120.  
  121.     log("Mop server %s starting", myName);
  122.  
  123. #define US mopHdrPtr->header.ether_dhost
  124. #define THEM mopHdrPtr->header.ether_shost
  125.     while (1) {
  126.     len = read(mopFd, buf, 1000);
  127.  
  128.     if (debug>1) {
  129.         log("Packet from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x to %2.2x:%2.2x:%2.2x:%2.2x.", THEM[0],THEM[1],THEM[2],THEM[3],THEM[4],THEM[5], US[0],
  130.             US[1], US[2],US[3],US[4],US[5]);
  131.     }
  132.  
  133.     if (!bcmp(&multiAddr, US, sizeof(Net_EtherAddress))) {
  134.         if (debug) {
  135.         log("Got a broadcast packet");
  136.         }
  137.         Host_Start();
  138.         theirNetAddress.type = NET_ADDRESS_ETHER;
  139.         bcopy(THEM,&theirNetAddress.address.ether,
  140.             sizeof(Net_EtherAddress));
  141.         theirEntry = Host_ByNetAddr(&theirNetAddress);
  142.         Host_End();
  143.         if (theirEntry == NULL) {
  144.         log("Packet from unknown %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
  145.             THEM[0],THEM[1],THEM[2],THEM[3],THEM[4],THEM[5]);
  146.         continue;
  147.         }
  148.     } else if (bcmp(&myAddr, US, sizeof(Net_EtherAddress))) {
  149.         log("Mystery packet to %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
  150.             US[0],US[1],US[2],US[3],US[4],US[5]);
  151.         continue;
  152.     }
  153.  
  154.     if (debug>2) {
  155.         log("Received: %d", mopHdrPtr->code);
  156.     }
  157.  
  158.     if (mode == WAITING) {
  159.         bcopy(THEM,client,6);
  160.     } else if (bcmp(client, THEM,6)!=0) {
  161.         /*
  162.          * We can't handle two clients at once, so this one must wait.
  163.          */
  164.         if (debug) {
  165.         log("Mop request collision");
  166.         }
  167.         continue;
  168.     }
  169.      
  170.     if (mopHdrPtr->code == MOP_REQ) {
  171.         if (initRequest(buf)<0) continue;
  172.     }
  173.     if (mode==SENDING && (mopHdrPtr->code == MOP_REQ_LOAD ||
  174.         mopHdrPtr->code == MOP_REQ)) {
  175.         alarm(TIMEOUTSEC);
  176.         sendData(buf);
  177.     } else if (mode==DONE && mopHdrPtr->code == MOP_REQ_LOAD) {
  178.         if (debug) {
  179.         mopReqLoad *mopReqLoadPtr = (mopReqLoad *)(buf+HDR_LEN);
  180.         log("Load completed: status %d", mopReqLoadPtr->error);
  181.         }
  182.         alarm(0);
  183.         close(bootFd);
  184.         mode = WAITING;
  185.     } else {
  186.         log("Out of order function: %d", mopHdrPtr->code);
  187.         if (mode==1) {
  188.         close(bootFd);
  189.         }
  190.         mode = WAITING;
  191.     }
  192.     }
  193. }
  194.  
  195. /*
  196.  * Transmit a packet.
  197.  */
  198. mopXmit(fd, src, dst, len, code, buf)
  199.     int fd;
  200.     u_char *src;
  201.     u_char *dst;
  202.     int    len;
  203.     int code;
  204.     char *buf;
  205. {
  206.     short shortVal;
  207.     mopHdr *mopHdrPtr = (mopHdr *)buf;
  208.     if (debug>2) {
  209.     log("Transmitting: code %d, len: %d", code, len);
  210.     }
  211.     bcopy(src, mopHdrPtr->header.ether_shost, 6);
  212.     bcopy(dst, mopHdrPtr->header.ether_dhost, 6);
  213.     shortVal = SWAP2(NET_ETHER_MOP);
  214.     bcopy(&shortVal, &mopHdrPtr->header.ether_type, sizeof(short));
  215.     shortVal = len+1; /* One byte for the code */
  216.     bcopy(&shortVal, &mopHdrPtr->len, sizeof(short));
  217.     mopHdrPtr->code = code;
  218.     if (write(fd, buf, HDR_LEN+len)<0) {
  219.     log("MOP packet write error: %d", errno);
  220.     }
  221. }
  222.  
  223. /*
  224.  * Find how much code we should give the client.
  225.  */
  226. int
  227. findStart(inFd, fileOffset, loadAddr, progLen, startAddr)
  228. int inFd;            /* Fd for us to use */
  229. int *fileOffset;        /* Return: offset of program in file. */
  230. int *loadAddr;            /* Return: address to load program. */
  231. int *progLen;            /* Return: the length of the program. */
  232. int *startAddr;            /* Return: start of execution. */
  233. {
  234.     struct filehdr fileHdr;
  235.     struct aouthdr aoutHdr;
  236.  
  237.     read(inFd, &fileHdr, sizeof(struct filehdr));
  238.     read(inFd, &aoutHdr, sizeof(struct aouthdr));
  239.     aoutHdr.magic = UNSWAP2(aoutHdr.magic);
  240.     aoutHdr.vstamp = UNSWAP2(aoutHdr.vstamp);
  241.     aoutHdr.text_start = UNSWAP4(aoutHdr.text_start);
  242.     aoutHdr.tsize = UNSWAP4(aoutHdr.tsize);
  243.     aoutHdr.dsize = UNSWAP4(aoutHdr.dsize);
  244.     aoutHdr.entry = UNSWAP4(aoutHdr.entry);
  245.     fileHdr.f_magic = UNSWAP2(fileHdr.f_magic);
  246.     fileHdr.f_nscns = UNSWAP2(fileHdr.f_nscns);
  247.     if (fileHdr.f_magic != MIPSELMAGIC || aoutHdr.magic != OMAGIC) {
  248.     log("Bad magic number on boot file %s", filename);
  249.     log("f_magic = %x, want %x.  a_magic = %x, want %x",
  250.         fileHdr.f_magic, MIPSELMAGIC, aoutHdr.magic, OMAGIC);
  251.     }
  252.     *fileOffset = N_TXTOFF(fileHdr, aoutHdr);
  253.     *loadAddr = aoutHdr.text_start;
  254.     *progLen = aoutHdr.tsize+aoutHdr.dsize;
  255.     *startAddr = aoutHdr.entry;
  256.     if (debug) {
  257.     log("File: offset: %x, addr: %x, len: %x, start: %x\n", *fileOffset,
  258.         *loadAddr, *progLen, *startAddr);
  259.     }
  260. }
  261.  
  262. /*
  263.  * Open our input file.
  264.  */
  265. int
  266. openFile(mopPtr)
  267. mopReq *mopPtr;
  268. {
  269.     int bootFd;
  270.     char *machineType;
  271.     char *name;
  272.     char *strPtr;
  273.  
  274.     if (mopPtr->devType == 0x43) {
  275.     machineType = "ds3100.md";
  276.     } else if (mopPtr->devType == 0x5e) {
  277.     machineType = "ds5000.md";
  278.     } else {
  279.     log("Unknown machine type %d", mopPtr->devType);
  280.     return -1;
  281.     }
  282.     name = (mopPtr->softID != '\0') ? &mopPtr->softID : "sprite";
  283.     /*
  284.      * Drop any boot flags.
  285.      */
  286.     strPtr = strchr(name,' ');
  287.     if (strPtr != NULL) {
  288.     *strPtr = '\0';
  289.     }
  290.     sprintf(filename,"%s/%s/%s", BOOT_DIR, machineType, name);
  291.     bootFd = open(filename, O_RDONLY, 0);
  292.     if (debug) {
  293.     log("Booting %s", filename);
  294.     }
  295.     if (bootFd < 0) {
  296.     log("Couldn't open %s", filename);
  297.     /*
  298.      * See if we have an error file we can return.
  299.      */
  300.     sprintf(filename,"%s/%s/%s", BOOT_DIR, machineType, "err");
  301.     bootFd = open(filename, O_RDONLY, 0);
  302.     if (bootFd < 0) {
  303.         return -1;
  304.     }
  305.     }
  306.     return bootFd;
  307. }
  308.  
  309. /*
  310.  * log an error message
  311.  *
  312.  */
  313. static void
  314. log(va_alist)
  315.     va_dcl
  316. {
  317.         FILE *fp;
  318.         char *format;
  319.         va_list args;
  320.         time_t now;
  321.         char *t;
  322.  
  323.         va_start(args);
  324.         time(&now);
  325.         t = asctime(localtime(&now));
  326.         /* remove the newline */
  327.         t[24] = '\0';
  328.         if ((fp = fopen(mopdlog, openFlags)) == NULL) {
  329.         perror(mopdlog);
  330.         return;
  331.     }
  332.         fprintf(fp, "[mopd %s]: ", t);
  333.         format = va_arg(args, char *);
  334.         vfprintf(fp, format, args);
  335.         putc('\n', fp);
  336.         fclose(fp);
  337.         return;
  338. }
  339.  
  340. /*
  341.  * Handle an initial request.
  342.  */
  343. initRequest(buf)
  344.     char *buf;
  345. {
  346.     mopReq *mopPtr = (mopReq *)(buf+HDR_LEN);
  347.  
  348.     if (mode!=WAITING) {
  349.     if (debug) {
  350.         log("Wasn't expecting request");
  351.     }
  352.     }
  353.     seq = 0;
  354.     seqHi = 0;
  355.     bootFd = openFile(mopPtr);
  356.     if (bootFd<0) {
  357.     if (debug) {
  358.         log("openFile failed");
  359.     }
  360.     mode = WAITING;
  361.     return -1;
  362.     }
  363.     mode = SENDING;
  364.     if (findStart(bootFd, &fileOffset, &loadAddr, &length,
  365.         &startAddr)<0) {
  366.     if (debug) {
  367.         log("findStart failed");
  368.     }
  369.     mode = WAITING;
  370.     close(bootFd);
  371.     return -1;
  372.     }
  373.     return 0;
  374. }
  375.  
  376. /*
  377.  * Send the next data packet.
  378.  */
  379. sendData(buf)
  380. {
  381.     mopHdr *mopHdrPtr = (mopHdr *)buf;
  382.     mopLoad *mopLoadPtr = (mopLoad *)(buf+HDR_LEN);
  383.     mopReqLoad *mopReqLoadPtr = (mopReqLoad *)(buf+HDR_LEN);
  384.     mopParamLoad *mopParamLoadPtr = (mopParamLoad *)(buf+HDR_LEN);
  385.     int intVal;
  386.     int seqReq;
  387.     int curPos, toRead;
  388.     /*
  389.      * Check the sequence numbers.
  390.      */
  391.     if (mopHdrPtr->code == MOP_REQ) {
  392.     seqReq = 0;
  393.     } else {
  394.     seqReq = mopReqLoadPtr->loadNum;
  395.     if (debug) {
  396.         log("Requested sequence number %d\n", seqReq);
  397.     }
  398.     if (mopReqLoadPtr->error != 0) {
  399.         if (debug) {
  400.         log("Load error status %d", mopReqLoadPtr->error);
  401.         }
  402.         mode = WAITING;
  403.         close(bootFd);
  404.         return;
  405.     }
  406.     }
  407.     if (seqReq != seq) {
  408.     log("Out of sequence request %d vs %d from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", seqReq, seq, THEM[0], THEM[1], THEM[2], THEM[3], THEM[4], THEM[5]);
  409.     /* Somehow we need to get back into sync. */
  410.     seq = seqReq;
  411.     return;
  412.     }
  413.     /*
  414.      * Transmit the data.
  415.      */
  416.     curPos = PACKET_SIZE*(seq+seqHi*256);
  417.     toRead = length-curPos;
  418.     if (toRead > PACKET_SIZE) {
  419.     toRead = PACKET_SIZE;
  420.     }
  421.     if (toRead > 0) {
  422.     lseek(bootFd, fileOffset+curPos, 0);
  423.     if (read(bootFd, buf+HDR_LEN+MOPLOAD_LEN, toRead) != toRead) {
  424.         log("Short boot file %s",filename);
  425.         mode = WAITING;
  426.         close(bootFd);
  427.         return;
  428.     }
  429.     mopLoadPtr->loadNum = seq;
  430.     intVal = UNSWAP4((loadAddr + curPos));
  431.     bcopy(&intVal, mopLoadPtr->loadAddr, sizeof(int));
  432.     toRead = PACKET_SIZE; /* HACK */
  433.     mopXmit(mopFd, &myAddr, client, MOPLOAD_LEN+toRead, MOP_LOAD, buf);
  434.     } else {
  435.     mopParamLoadPtr->loadNum = seq;
  436.     mopParamLoadPtr->parameters = 0;
  437.     intVal = UNSWAP4(startAddr);
  438.     if (debug) {
  439.         log("Transferring to %x", startAddr);
  440.     }
  441.     bcopy(&intVal, &mopParamLoadPtr->parameters+1, sizeof(int));
  442.     mopXmit(mopFd, &myAddr, client, sizeof(mopParamLoad)+sizeof(int),
  443.         MOP_PARAM_LOAD_XFER, buf);
  444.     mode = DONE;
  445.     }
  446.     seq++;
  447.     if (seq==256) {
  448.     seq=0;
  449.     seqHi++;
  450.     }
  451. }
  452.  
  453. /*
  454.  * Handle a timeout.
  455.  */
  456. timer()
  457. {
  458.     if (mode != WAITING) {
  459.     log("Timeout");
  460.     close(bootFd);
  461.     mode = WAITING;
  462.     }
  463. }
  464.